package FlowGram.Application.Parser;

import java.util.ArrayList;
import java.util.Iterator;

import FlowGram.Application.Parser.Controllers.*;
import FlowGram.Application.Parser.Actions.FinchAction;
import FlowGram.Application.Parser.Actions.Control.FunctionDefinition;


/**
 * 
 * @author thackray
 *
 */
public class FinchProgramFlow {

	
	 
	protected ArrayList<FinchAction> actions;
	protected ArrayList<FinchExecutionLogger> loggers;
	protected ArrayList<FinchController> controllers;
	
	protected static String NL = "\r\n";
	
	
	
	public FinchProgramFlow(){
		this.actions = new ArrayList<FinchAction>();
		this.loggers = new ArrayList<FinchExecutionLogger>();
		this.controllers = new ArrayList<FinchController>();
	}
	public int size(){
		return this.actions.size();
	}
	public void enqueueAction(FinchAction action){
		this.actions.add(action);
	}
	public void insertActionAt(int i, FinchAction action){
		this.actions.add(i, action);
	}
	public FinchAction getActionAt(int i){
		return this.actions.get(i);
	}
	public FinchAction dequeueAction(){
		if(this.size() > 0){
			return this.actions.remove(0);
		}
		return null;
	}
	public FinchAction removeActionAt(int i){
		return this.actions.remove(i);
	}
	public void execute(){
		ArrayList<FinchAction> actionClone = (ArrayList<FinchAction>)this.actions.clone();
		
		Iterator<FinchAction> iter = actionClone.iterator();
		while(iter.hasNext()){
			FinchAction action = iter.next();
			if(!(action instanceof FunctionDefinition)){
				this.logExecution(action.logMessage());
				for(int i=0; i<this.controllers.size(); i++){
					action.execute(this.controllers.get(i));
				}
			}
		}
		//this.actions = actionClone;
		actionClone=null;
	}
	public String toCode(int indent){
		ArrayList<FinchAction> actionClone = (ArrayList<FinchAction>)this.actions.clone();
		FinchAction action;
		String codeBuffer = "";
		while((action = this.dequeueAction()) != null){
			//this.logExecution(action.logMessage());
			codeBuffer += action.getIndent(indent)+action.toCode(indent)+NL;
		}
		this.actions = actionClone;
		actionClone=null;
		return codeBuffer;
	}
	
	public String toCode(){
		return this.toCode(0);
	}
	public String toHTML(String idPrefix){
		ArrayList<FinchAction> actionClone = (ArrayList<FinchAction>)this.actions.clone();

		String codeBuffer = "";
		Iterator<FinchAction> iter = actionClone.iterator();
		int i=0;
		while(iter.hasNext()){
			String id;
			if(idPrefix.equals("")){
				id = ""+i;
			}else{
				id = idPrefix+"."+i;
			}
			FinchAction action = iter.next();
			//this.logExecution(action.logMessage());
			codeBuffer += "<div id=\""+id+"\" class=\""+action.getClass().getSimpleName().toLowerCase()+"\">"+action.toHTML(id)+"</div>";
			i++;
		}
		actionClone=null;
		return codeBuffer;
	}
	public void addLogger(FinchExecutionLogger logger){
		this.loggers.add(logger);
	}
	public void addController(FinchController controller){
		this.controllers.add(controller);
	}
	public void addController(ArrayList<FinchController> controllers){
		this.controllers.addAll(controllers);
	}
	public boolean hasController(String name){
		for(int i=0; i < this.controllers.size(); i++){
			if(this.controllers.get(i).getName().equals(name)){
				return true;
			}
		}
		return false;
	}
	public void logExecution(String message){
		for(int i=0; i < this.loggers.size(); i++){
			this.loggers.get(i).log(message);
		}
	}
	
	
}




